﻿#include "socket.h"
#include "epoller.h"
#include "channel.h"
#include <iostream>

void OnClientError(Channel *channel)
{
    std::cout << "client error" << std::endl;
}

void OnClientClose(Channel *channel)
{
    std::cout << "client close" << std::endl;
    channel->remove();
    delete channel;
}

void OnClientAny(Channel *channel)
{
    std::cout << "client any" << std::endl;
}
void OnClientWrite(Channel *channel)
{
    std::cout << "client write" << std::endl;
    std::string response = "sfwnb";
    int ret = ::send(channel->getFd(), response.c_str(), response.size(), 0);
    if(ret < 0)
    {
        std::cout << "send failed, client_fd: " << channel->getFd() << std::endl;
        OnClientClose(channel);
        return;
    }
    channel->disableWrite();
}
void OnClientRead(Channel *channel)
{
    int fd = channel->getFd();
    char buf[1024];
    ssize_t ret = ::recv(fd, buf, sizeof(buf), 0);
    if(ret < 0)
    {
        std::cout << "client disconnected, client_fd: " << fd << std::endl;
        OnClientClose(channel);
        return;
    }
    std::cout << "recv: " << buf << std::endl;
    channel->enableWrite();
}


bool AcceptNewClient(Epoller *epoller, Channel *channel)
{
    int listen_fd = channel->getFd();
    int client_fd = accept(listen_fd, NULL, NULL);
    if(client_fd < 0)
    {
        std::cout << "accept failed, listen_fd: " << listen_fd << std::endl;
        return false;
    }
    Channel *client_channel = new Channel(epoller, client_fd);
    client_channel->setReadCallback(std::bind(OnClientRead, client_channel));
    client_channel->setWriteCallback(std::bind(OnClientWrite, client_channel));
    client_channel->setErrorCallback(std::bind(OnClientError, client_channel));
    client_channel->setCloseCallback(std::bind(OnClientClose, client_channel));
    client_channel->setAnyCallback(std::bind(OnClientAny, client_channel));
    client_channel->enableRead();
    return true;
}

int main() 
{
    // 创建epoller
    Epoller epoll;
    Socket socket;
    socket.createTcpServer(58888);
    // 创建channel
    Channel channel(&epoll, socket.fd());
    // 添加可读监控
    channel.setReadCallback(std::bind(AcceptNewClient, &epoll, &channel));
    channel.enableRead();

    while(true)
    {
        std::vector<Channel *> actives;
        epoll.waitEvent(actives);
        for(auto active : actives)
        {
            active->handleEvent();
        }
    }
    socket.close();
    return 0;
}